import pygame
import sys
import random

# 初始化Pygame
pygame.init()

# 常量定义
GRID_SIZE = 50  # 格子大小（像素）
BOARD_SIZE = 15  # 棋盘尺寸（15x15）
MARGIN = 30  # 调整棋盘边距，使棋盘更合适
WIDTH = MARGIN * 2 + GRID_SIZE * BOARD_SIZE  # 窗口宽度
HEIGHT = MARGIN * 2 + GRID_SIZE * BOARD_SIZE  # 棋盘高度

# 按钮设置
BUTTON_HEIGHT = 50  # 按钮高度
BUTTON_WIDTH = 120  # 按钮宽度
BUTTON_MARGIN = 20  # 按钮间距
BUTTON_Y = HEIGHT + MARGIN  # 按钮区域Y坐标，位于棋盘下方
WINDOW_HEIGHT = HEIGHT + MARGIN * 2 + BUTTON_HEIGHT  # 窗口总高度

# 按钮文本和位置（优化布局）
BUTTONS = [
    {"text": "开始游戏", "x": MARGIN, "y": BUTTON_Y, "width": BUTTON_WIDTH, "height": BUTTON_HEIGHT},
    {"text": "游戏说明", "x": MARGIN + BUTTON_WIDTH + BUTTON_MARGIN, "y": BUTTON_Y, "width": BUTTON_WIDTH,
     "height": BUTTON_HEIGHT},
    {"text": "认输", "x": MARGIN + (BUTTON_WIDTH + BUTTON_MARGIN) * 2, "y": BUTTON_Y, "width": BUTTON_WIDTH,
     "height": BUTTON_HEIGHT},
    {"text": "退出游戏", "x": MARGIN + (BUTTON_WIDTH + BUTTON_MARGIN) * 3, "y": BUTTON_Y, "width": BUTTON_WIDTH,
     "height": BUTTON_HEIGHT},
]

# 按钮状态
button_states = {btn["text"]: False for btn in BUTTONS}  # 按钮是否被按下

# 创建窗口（确保尺寸正确）
screen = pygame.display.set_mode((WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("五子棋 - 人类(黑) VS AI(白)")
clock = pygame.time.Clock()

# 颜色定义
BG_COLOR = (205, 133, 63)  # 木纹背景
LINE_COLOR = (0, 0, 0)  # 棋盘线颜色
BLACK = (0, 0, 0)  # 黑棋颜色
WHITE = (255, 255, 255)  # 白棋颜色

# 全局变量
board = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]  # 棋盘状态
current_player = 1  # 当前玩家（1:人类-黑，2:AI-白）
game_over = False  # 游戏是否结束
winner = None  # 获胜方


# 棋盘与棋子绘制
def draw_board():
    """绘制棋盘和棋子"""
    screen.fill(BG_COLOR)  # 填充背景

    # 绘制棋盘线（确保在可见区域内）
    for i in range(BOARD_SIZE):
        x = MARGIN + i * GRID_SIZE
        pygame.draw.line(screen, LINE_COLOR, (x, MARGIN), (x, MARGIN + (BOARD_SIZE - 1) * GRID_SIZE), 2)
        y = MARGIN + i * GRID_SIZE
        pygame.draw.line(screen, LINE_COLOR, (MARGIN, y), (MARGIN + (BOARD_SIZE - 1) * GRID_SIZE, y), 2)

    # 绘制棋子
    for i in range(BOARD_SIZE):
        for j in range(BOARD_SIZE):
            if board[i][j] == 1:  # 黑棋
                pos = (MARGIN + i * GRID_SIZE, MARGIN + j * GRID_SIZE)
                pygame.draw.circle(screen, BLACK, pos, GRID_SIZE // 2 - 2)
            elif board[i][j] == 2:  # 白棋
                pos = (MARGIN + i * GRID_SIZE, MARGIN + j * GRID_SIZE)
                pygame.draw.circle(screen, WHITE, pos, GRID_SIZE // 2 - 2)

#绘制功能按钮
def draw_buttons():
    """绘制底部按钮"""
    for btn in BUTTONS:
        # 按钮颜色
        color = (150, 150, 150) if button_states[btn["text"]] else (200, 200, 200)
        hover_color = (180, 180, 180)

        # 获取鼠标位置，判断是否悬停
        mouse_x, mouse_y = pygame.mouse.get_pos()
        is_hover = btn["x"] <= mouse_x <= btn["x"] + btn["width"] and btn["y"] <= mouse_y <= btn["y"] + btn["height"]

        # 绘制按钮
        pygame.draw.rect(screen, hover_color if is_hover else color,
                         (btn["x"], btn["y"], btn["width"], btn["height"]), border_radius=10)
        pygame.draw.rect(screen, (0, 0, 0),
                         (btn["x"], btn["y"], btn["width"], btn["height"]), 2, border_radius=10)

        # 绘制按钮文本（确保字体加载正确）
        try:
            font = pygame.font.Font("msyh.ttc", 28)  # 调整字体大小
        except FileNotFoundError:
            font = pygame.font.SysFont("Microsoft YaHei", 28)
        text = font.render(btn["text"], True, (0, 0, 0))
        text_rect = text.get_rect(center=(btn["x"] + btn["width"] // 2, btn["y"] + btn["height"] // 2))
        screen.blit(text, text_rect)

#处理按钮点击事件
def handle_button_click(btn_text):
    """处理按钮点击事件"""
    global board, current_player, game_over, winner
    if btn_text == "开始游戏":
        board = [[0] * BOARD_SIZE for _ in range(BOARD_SIZE)]
        current_player = 1
        game_over = False
        winner = None
        print("游戏已重新开始")
    elif btn_text == "游戏说明":
        show_game_instructions()
    elif btn_text == "认输":
        if not game_over:
            game_over = True
            winner = 2 if current_player == 1 else 1
            print(f"玩家{current_player}认输，玩家{winner}获胜！")
    elif btn_text == "退出游戏":
        pygame.quit()
        sys.exit()

#显示游戏结构
def show_game_instructions():
    """显示游戏说明弹窗"""
    instructions = [
        "五子棋游戏规则：",
        "- 对局双方各执一色棋子（黑/白）",
        "- 黑先、白后，交替下子，每次只能下一子",
        "- 先形成五子连线（横、竖、斜向均可）者获胜",
        "操作：",
        "- 点击棋盘落子，按钮控制游戏流程"
    ]

    # 创建半透明覆盖层
    overlay = pygame.Surface((WIDTH, WINDOW_HEIGHT), pygame.SRCALPHA)
    overlay.fill((0, 0, 0, 180))
    screen.blit(overlay, (0, 0))

    # 绘制说明文本
    try:
        font = pygame.font.Font("msyh.ttc", 26)
    except FileNotFoundError:
        font = pygame.font.SysFont("Microsoft YaHei", 26)

    y_offset = MARGIN * 2
    for line in instructions:
        text = font.render(line, True, (255, 255, 255))
        screen.blit(text, (MARGIN * 2, y_offset))
        y_offset += 35

    # 绘制关闭提示
    close_text = font.render("按任意键关闭", True, (255, 255, 255))
    screen.blit(close_text, (WIDTH // 2 - close_text.get_width() // 2, WINDOW_HEIGHT - MARGIN * 2))

    pygame.display.flip()

    # 等待用户按键
    waiting = True
    while waiting:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
                waiting = False


# 胜负判断逻辑
def check_win(x, y, color):
    directions = [(0, 1), (1, 0), (1, 1), (1, -1)]
    for dx, dy in directions:
        count = 1
        # 正向遍历
        i, j = x + dx, y + dy
        while 0 <= i < BOARD_SIZE and 0 <= j < BOARD_SIZE and board[i][j] == color:
            count += 1
            i += dx
            j += dy
        # 反向遍历
        i, j = x - dx, y - dy
        while 0 <= i < BOARD_SIZE and 0 <= j < BOARD_SIZE and board[i][j] == color:
            count += 1
            i -= dx
            j -= dy
        if count >= 5:
            return True
    return False


# AI策略
def ai_move():
    best_score = -1
    best_pos = None
    ai_color = 2
    opponent_color = 1
    empty_cells = [(i, j) for i in range(BOARD_SIZE) for j in range(BOARD_SIZE) if board[i][j] == 0]

    if not empty_cells:
        return None

    for i, j in empty_cells:
        # 评估AI落子
        board[i][j] = ai_color
        score_self = evaluate(i, j, ai_color)
        board[i][j] = 0

        # 评估人类落子
        board[i][j] = opponent_color
        score_opp = evaluate(i, j, opponent_color)
        board[i][j] = 0

        total_score = score_self + score_opp * 2
        if total_score > best_score:
            best_score = total_score
            best_pos = (i, j)

    return best_pos if best_pos else random.choice(empty_cells)

#评估位置价值
def evaluate(x, y, color):
    max_count = 0
    directions = [(0, 1), (1, 0), (1, 1), (1, -1)]
    for dx, dy in directions:
        count = 1
        i, j = x + dx, y + dy
        while 0 <= i < BOARD_SIZE and 0 <= j < BOARD_SIZE and board[i][j] == color:
            count += 1
            i += dx
            j += dy
        i, j = x - dx, y - dy
        while 0 <= i < BOARD_SIZE and 0 <= j < BOARD_SIZE and board[i][j] == color:
            count += 1
            i -= dx
            j -= dy
        if count > max_count:
            max_count = count
    return max_count


# 坐标转换函数
def get_board_position(mouse_x, mouse_y):
    min_distance = float('inf')
    best_i, best_j = None, None
    threshold = GRID_SIZE / 2

    for i in range(BOARD_SIZE):
        for j in range(BOARD_SIZE):
            cross_x = MARGIN + i * GRID_SIZE
            cross_y = MARGIN + j * GRID_SIZE
            distance = ((mouse_x - cross_x) ** 2 + (mouse_y - cross_y) ** 2) ** 0.5
            if distance < min_distance:
                min_distance = distance
                best_i, best_j = i, j

    if min_distance <= threshold:
        return best_i, best_j
    return None, None


# 主循环
def main():
    global current_player, game_over, winner, board
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

            if event.type == pygame.MOUSEBUTTONDOWN:
                x, y = event.pos
                # 检查按钮点击
                for btn in BUTTONS:
                    if btn["x"] <= x <= btn["x"] + btn["width"] and btn["y"] <= y <= btn["y"] + btn["height"]:
                        button_states[btn["text"]] = True
                        handle_button_click(btn["text"])
                        pygame.time.delay(100)
                        button_states[btn["text"]] = False

                # 人类落子
                if not game_over and current_player == 1:
                    i, j = get_board_position(x, y)
                    if i is not None and j is not None and board[i][j] == 0:
                        board[i][j] = current_player
                        if check_win(i, j, current_player):
                            game_over = True
                            winner = current_player
                        else:
                            current_player = 2

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    board = [[0] * BOARD_SIZE for _ in range(BOARD_SIZE)]
                    current_player = 1
                    game_over = False
                    winner = None

        # AI落子
        if not game_over and current_player == 2:
            pygame.time.delay(500)
            ai_pos = ai_move()
            if ai_pos:
                i, j = ai_pos
                board[i][j] = current_player
                if check_win(i, j, current_player):
                    game_over = True
                    winner = current_player
                else:
                    current_player = 1

        # 绘制界面（确保顺序正确）
        screen.fill(BG_COLOR)
        draw_board()
        draw_buttons()

        # 显示游戏结果
        if game_over:
            try:
                font = pygame.font.Font("msyh.ttc", 40)
            except FileNotFoundError:
                font = pygame.font.SysFont("Microsoft YaHei", 40)

            if winner == 1:
                text = font.render("你赢了！按R键重开", True, BLACK)
            elif winner == 2:
                text = font.render("AI赢了！按R键重开", True, BLACK)
            else:
                text = font.render("和棋！按R键重开", True, BLACK)
            screen.blit(text, (WIDTH // 2 - text.get_width() // 2, MARGIN // 2))

        pygame.display.flip()
        clock.tick(30)


if __name__ == "__main__":
    main()